﻿#!/usr/bin/perl
use LWP::UserAgent;
use HTTP::Request::Common qw(GET POST);
use HTML::Parser; use URI;
use HTML::Entities;

use constant MAINPAGE =>
  'http://en.wikipedia.org/wiki/Wikipedia:Tutorial_%28Keep_in_mind%29/sandbox';
use constant EDITPAGE => 'http://en.wikipedia.org/w/index.php'
  . '?title=Wikipedia:Tutorial_%28Keep_in_mind%29/sandbox';

# Na modyfikowanej stronie są elementy wprowadzania danych, które nas interesują.
my @wpTags = qw(wpEditToken wpAutoSummary wpStarttime wpEdittime wpSave );

sub findPageData {
    my ( $self, $tag, $attr ) = @_;
    # Wysyłamy sygnał do procedury obsługi endHandler o tym, czy znaleźliśmy tekst.
    if ( $attr->{name} eq "wpTextbox1" ) {
        $main::wpTextboxFound = 1;
        return;
    }
    elsif ( grep( /$attr->{name}/, @wpTags ) > 0 ) {
    # Jeśli to jest jeden z parametrów formularza, który nas interesuje,
    # rejestrujemy wartość parametru do wykorzystania podczas późniejszych operacji przesyłania.
        $main::parms{ $attr->{name} } = $attr->{value};
        return;
    }
}

# Poniższa procedura jest wywoływana w odniesieniu do znaczników zamykających, na przykład </textarea>.
sub endHandler {
    next unless $main::wpTextboxFound;
    my ( $self, $tag, $attr, $skipped ) = @_;
    if ( $tag eq "textarea" ) {
        $main::parms{"wpTextbox1"} = $skipped;
        undef $main::wpTextboxFound;
    }
}

sub checkError {
    my $resp = shift;
    if ( ( $resp->code() < 200 ) || ( $resp->code() >= 400 ) ) {
        print "Błąd: " . $resp->status_line . "\n";
        exit 1;
    }
}

###
### PROGRAM GŁÓWNY
###

# Najpierw pobieramy główną stronę piaskownicy Wikipedii. W ten sposób potwierdzamy, że mamy
# połączenie i upewniamy się, czy działa.
$UA   = LWP::UserAgent->new();
$req = HTTP::Request->new( GET => MAINPAGE );
$resp = $UA->request($req);

checkError($resp);

# Teraz pobieramy wersję strony do edycji.
$req->uri( EDITPAGE . '&action=edit' );
$resp = $UA->request($req);

checkError($resp);

# Tworzymy parser, którego zadaniem będzie analiza modyfikowanej strony i znalezienie na niej tekstu.
my $p = HTML::Parser->new(
    api_version => 3,
    start_h       => [ \&findPageData, "self,tagname,attr" ],
    end_h         => [ \&endHandler, "self,tagname,attr,skipped_text" ],
    unbroken_text => 1,
    attr_encoded  => 0,
    report_tags   => [qw(textarea input)]
);
$p->parse( $resp->content );
$p->eof;

# W tekście są zakodowane encje HTML (na przykład &lt; zamiast <).
# Musimy je zdekodować i przesłać „surowe” znaki.
$main::parms{wpTextbox1} = decode_entities($main::parms{wpTextbox1});

# Wprowadzenie prostych modyfikacji. Dołączenie tekstu do informacji zapisanych tam wcześniej.
$main::parms{wpTextbox1} .= "\r\n\r\n===Test 1===\r\n\r\n"
  . "ISBN: 9780596514839\r\n\r\nTo jest test.\r\n\r\n";

# Przesłanie modyfikacji metodą POST.
$req = HTTP::Request::Common::POST(
    EDITPAGE,
    Content_Type => 'form-data',
    Content      => \%main::parms
);
$req->uri( EDITPAGE . '&action=submit' );

$resp = $UA->request($req);
checkError($resp);
# Jeśli test się powiódł, spodziewamy się odpowiedzi 302 - przekierowanie.
